package perf;

import editor.PwnIDE;
import editor.headers.Header;
import model.code.CodeFileChunk;
import model.code.Function;
import model.code.line.Line;
import model.code.line.SingleLine;
import observer.ObservedLong;
import observer.ObservedString;
import util.Pair;

import java.awt.*;

/**
 * This class stores information about a performance test in a {@link model.code.Function}
 *
 * To configure, after loading languages in PwnIDE.java:
 * Function.setTestNameObserver(PerformanceTestInfo.nameObserver);
 *
 * To add the HeaderComponent in Header constructor, instead of adding the ParameterTable normally:
 *	if (function.getTestFunctionInfo()!=null && function.getTestFunctionInfo() instanceof PerformanceTestInfo) {
 *		components.add(new PerformanceTestOptions(this,function.getTestFunctionInfo()));
 *	}
 *	else {
 *		components.add(new ParameterTable(this));
 *	}
 *
 * To add the performance test icon in Images:
 * 	public static final Image		PERFORMANCE_RUN		= new ImageIcon(PwnIDE.IMAGE_DIR+"PerformanceFunction.png").getImage();
 * 
 * @author Neil Dickson
 */
public class PerformanceTestInfo {
	public final ObservedLong	maxNumTestResults;
	public final SingleLine	testGroupName;
	public final ObservedString	scaling;

	public static final String	SCALING_1		= "O(1)";
	public static final String	SCALING_LOGN	= "O(logn)";
	public static final String	SCALING_N		= "O(n)";
	public static final String	SCALING_NLOGN	= "O(nlogn)";
	public static final String	SCALING_N2		= "O(n^2)";
	public static final String[]	SCALINGS	= {SCALING_1,SCALING_LOGN,SCALING_N,SCALING_NLOGN,SCALING_N2};
	public static final String[]	BRIEF_SCALINGS	= {"1","l","n","nl","n2"};

	public static final SingleLine.LineObserver	nameObserver = new SingleLine.LineObserver() {
		public void valueChanged(SingleLine line, String oldValue) {
			// NOTE: This avoid creating too many unnecessary strings by checking if the first letter is P first
			if (line.getParent()!=null && line.getParent() instanceof Function) {
				Function function = (Function)line.getParent();
				if (line.length()>5 && line.getText()[0]=='P' && line.toString(0,5).equals("PTest") && function.getTestFunctionInfo()==null) {
					PerformanceTestInfo testInfo = new PerformanceTestInfo(function);
					function.setTestFunctionInfo(testInfo);
					function.getScope().add(PerformanceTestEncoder.instance.startFunction);
					function.getScope().add(PerformanceTestEncoder.instance.stopFunction);
					if (PwnIDE.ui!=null) {
						Pair<Header, Point> headerAndLocation = PwnIDE.ui.getHeaderAndLocation(function);
						if (headerAndLocation!=null && headerAndLocation.a!=null) {
							Header header = headerAndLocation.a;
							header.removeComponent(CodeFileChunk.LOCATION_PARAMETERS);
							PerformanceTestOptions options = new PerformanceTestOptions(header,testInfo);
							header.addComponent(options);
						}
					}
				}
				else if ((line.length()<=5 || !line.toString(0,5).equals("PTest")) && function.getTestFunctionInfo()!=null) {
					Pair<Header, Point> headerAndLocation = PwnIDE.ui.getHeaderAndLocation(function);
					Header header = headerAndLocation.a;
					if (header!=null) {
						header.removeComponent(CodeFileChunk.LOCATION_PARAMETERS);
						Header.ParameterTable params = new Header.ParameterTable(header);
						header.addComponent(params);
					}
					function.getScope().remove(PerformanceTestEncoder.instance.startFunction);
					function.getScope().remove(PerformanceTestEncoder.instance.stopFunction);
					function.setTestFunctionInfo(null);
				}
			}
		}
	};

	public PerformanceTestInfo(Function function) {
		maxNumTestResults = new ObservedLong(100000);
		testGroupName = new SingleLine(Line.EMPTY_CHAR_ARRAY,function,CodeFileChunk.LOCATION_PARAMETERS);
		scaling = new ObservedString(SCALING_N);
	}
}
